﻿using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using UnityEngine;
using UnityEngine.UI;

namespace Nirvana
{
    /// <summary>
    /// 用于图片镜像，节省图集内存大小：比如左右对称的图片，只要一半镜像就可以显示全了。
    /// </summary>
    [RequireComponent(typeof(RectTransform))]
    [AddComponentMenu("Nirvana/UI/Effects/Image Mirror")]
    public class UIImageMirror : BaseMeshEffect, ILayoutElement
    {
        public enum MirrorModeType
        {
            Horizontal,
            Vertical,
            Quad
        }
        [SerializeField]
        [Tooltip("The mirror type.")]
        private MirrorModeType mirrorMode;
        public MirrorModeType MirrorMode
        {
            get
            {
                return this.mirrorMode;
            }
            set
            {
                if (this.mirrorMode != value)
                {
                    this.mirrorMode = value;
                    if (base.graphic != null) base.graphic.SetVerticesDirty();
                }
            }
        }
        private Image _image;
        private Image Image
        {
            get
            {
                if (this._image == null) this._image = GetComponent<Image>();
                return _image;
            }
        }
        private Vector2 _offset;


        private List<UIVertex> GetImageVertex(List<UIVertex> _list)
        {
            if(Image.type ==  Image.Type.Simple) //图片必须为simple类型
            {
                return GetVertex(_list);
            }
            return _list;
        }
        private List<UIVertex> GetVertex(List<UIVertex> _list)
        {
            int index = 0;
            int count = _list.Count;
            if(this.mirrorMode == MirrorModeType.Horizontal)
            {
                int horNum = _list.Count * 2;
                if (_list.Capacity < horNum) _list.Capacity = horNum;
                CalucateVertex(_list, index, count, 0, 0, -this._offset.x / 2f, 0, false);
                index = count;
                count = _list.Count;
                CalucateVertex(_list, index, count, this._offset.x, 0, -this._offset.x / 2f, 0, true);
            }

           else if (this.mirrorMode == MirrorModeType.Vertical)
            {
                int horNum = _list.Count * 2;
                if (_list.Capacity < horNum) _list.Capacity = horNum;
                CalucateVertex(_list, index, count, 0, 0, 0,this._offset.y / 2f, false);
                index = count;
                count = _list.Count;
                CalucateVertex(_list, index, count, 0,-this._offset.y, 0, this._offset.x / 2f, true);
            }
            else
            {
                int horNum = _list.Count * 4;
                if (_list.Capacity < horNum) _list.Capacity = horNum;
                CalucateVertex(_list, index, count, 0, 0, -this._offset.x / 2f, this._offset.y / 2f, false);
                index = count;
                count = _list.Count;
                CalucateVertex(_list, index, count, this._offset.x, 0, -this._offset.x / 2f, this._offset.y / 2f, false);
                index = count;
                count = _list.Count;
                CalucateVertex(_list, index, count, 0, -this._offset.y, -this._offset.x / 2f, this._offset.y / 2f,false);
                index = count;
                count = _list.Count;
                CalucateVertex(_list, index, count, this._offset.x, -this._offset.y, -this._offset.x / 2f, this._offset.y / 2f, true);
            }

            return _list;
        }

        private void CalucateVertex(List<UIVertex> _list,int startpos, int count,float width,float height, float widthhalf, float heighthalf,bool noAdd)
        {
            int num = _list.Count * 2;
            if(_list.Capacity < num)
            {
                _list.Capacity = num;
            }
            for(int i= startpos; i < count; i++)
            {
                UIVertex uivertex = _list[i];
                if (!noAdd)
                {
                    _list.Add(uivertex);
                }

                Vector3 pos = uivertex.position;
                int num2 = i % 6;
                switch (num2)
                {
                    case 0:
                    case 1:
                    case 5:
                        {
                            pos.x += width;
                            break;
                        }
                    case 2:
                    case 3:
                    case 4:
                        pos.x += widthhalf;
                        break;
                }
                switch (num2)
                {
                    case 0:
                    case 4:
                    case 5:
                        {
                            pos.y += height;
                            break;
                        }
                    case 1:
                    case 2:
                    case 3:
                        pos.y += heighthalf;
                        break;
                }
                uivertex.position = pos;
                _list[i] = uivertex;
            }
        }

#if UNITY_EDITOR
        protected override void OnValidate()
        {
            base.OnValidate();
            RectTransform rectTransform = base.transform as RectTransform;
            this._offset = rectTransform.sizeDelta;
            if (graphic != null)
            {
                graphic.SetVerticesDirty();
            }
        }
#endif

        protected override void OnEnable()
        {
            base.OnEnable();
            RectTransform rectTransform = base.transform as RectTransform;
            this._offset = rectTransform.sizeDelta;
            if (graphic != null)
            {
                graphic.SetVerticesDirty();
            }
        }

        #region 继承
        public float minWidth
        {
            get { return 0; }
        }

        public float preferredWidth
        {
            get {

                Image image = Image;
                if (image == null) return 0;
                switch (this.mirrorMode)
                {
                    case MirrorModeType.Horizontal:
                    case MirrorModeType.Quad:
                        return 2f * image.preferredWidth;
                }
                return image.preferredWidth;
            }
        }

        public float flexibleWidth
        {
            get { return -1f; }
        }

        public float minHeight
        {
            get { return 0; }
        }

        public float preferredHeight
        {
            get {
                Image image = Image;
                if(image == null) return 0;

                if (this.mirrorMode != UIImageMirror.MirrorModeType.Vertical && this.mirrorMode != UIImageMirror.MirrorModeType.Quad)
                {
                    return image.preferredHeight;
                }
                return 2f * image.preferredHeight;
            }
        }

        public float flexibleHeight
        {
            get { return -1f; }
        }

        public int layoutPriority
        {
            get { return 0; }
        }

        public void CalculateLayoutInputHorizontal()
        {
            
        }

        public void CalculateLayoutInputVertical()
        {
            
        }

        /// <summary>
        /// UI网格修改回调
        /// </summary>
        /// <param name="vh"></param>
        public override void ModifyMesh(VertexHelper vh)
        {
            if (!this.IsActive() || vh.currentVertCount <= 0)
            {
                return;
            }

            RectTransform rectTransform = transform as RectTransform;
            this._offset = rectTransform.rect.size;
            List<UIVertex> uivertexlist = VertexLists.Get();
            vh.GetUIVertexStream(uivertexlist);
            List<UIVertex> _list = GetImageVertex(uivertexlist);
            if(_list != null)
            {
                vh.Clear();
                vh.AddUIVertexTriangleStream(_list);
            }
            VertexLists.Set(uivertexlist);
        }
        #endregion
    }

}

